package org.jeecg.config.mybatis;

import cn.com.hhrcw.entity.EnInfo;
import cn.com.hhrcw.entity.OpDeliveryHistory;
import cn.com.hhrcw.entity.OpJob;
import cn.com.hhrcw.entity.SsSession;
import cn.com.hhrcw.es.entity.JobPositionDocument;
import cn.com.hhrcw.es.mapstruct.ElasticsearchConvert;
import cn.com.hhrcw.es.service.IElasticsearchService;
import cn.com.hhrcw.mapper.OpDeliveryHistoryMapper;
import cn.com.hhrcw.service.IEnInfoService;
import cn.com.hhrcw.service.IOpJobService;
import cn.com.hhrcw.service.ISsSessionService;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.convert.Convert;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.executor.Executor;
import org.apache.ibatis.mapping.MappedStatement;
import org.apache.ibatis.mapping.SqlCommandType;
import org.apache.ibatis.plugin.*;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;

import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.stream.Collectors;

/**
 * mybatis拦截器，自动注入创建人、创建时间、修改人、修改时间
 *
 * @Author scott
 * @Date 2019-01-19
 */
@Slf4j
@Intercepts({@Signature(type = Executor.class, method = "update", args = {MappedStatement.class, Object.class})})
public class ElasticsearchCacheInterceptor implements Interceptor {
    @Autowired
    private IElasticsearchService elasticsearchService;

    @Autowired
    private ElasticsearchConvert elasticsearchConvert;

    @Autowired
    @Lazy
    private IEnInfoService enInfoService;

    @Autowired
    @Lazy
    private IOpJobService jobService;

    @Autowired
    @Lazy
    private ISsSessionService sessionService;

    @Override
    public Object intercept(Invocation invocation) throws Throwable {
        Object object = invocation.proceed();
        if (Convert.toInt(object) <= 0) {
            return object;
        }
        Object[] args = invocation.getArgs();
        MappedStatement mappedStatement = (MappedStatement) args[0];
        SqlCommandType sqlCommandType = mappedStatement.getSqlCommandType();
        switch (sqlCommandType) {
            case UPDATE:
                Object param = ((Map) args[1]).get("param1");
                if (param instanceof OpJob) {
                    OpJob updateJob = (OpJob) ((Map) args[1]).get("param1");
                    updateJob = jobService.getById(updateJob.getId());
                    //专场未发布不添加到es
                    if (updateJob.getBsType() == 1) {
                        SsSession session = sessionService.getById(updateJob.getBsId());
                        if (!session.getPubFlag()) {
                            elasticsearchService.delete(JobPositionDocument.class, updateJob.getId());
                            break;
                        }
                    }
                    EnInfo updateJobEnInfo = enInfoService.getById(updateJob.getCompanyId());
                    Integer postNum = updateJobEnInfo.getPostNum();
                    if (updateJob.getRecruitmentState() == 0 && !updateJob.getDelFlag() && !updateJobEnInfo.getDelFlag() && updateJobEnInfo.getEnabled()) {
                        //postNum += 1;
                        JobPositionDocument document = elasticsearchConvert.toJobPosition(updateJob, updateJobEnInfo);
                        elasticsearchService.add(document);
                    } else {
                        postNum -= 1;
                        elasticsearchService.delete(JobPositionDocument.class, updateJob.getId());
                    }
                    updateJobEnInfo.setPostNum(postNum);
                    enInfoService.getBaseMapper().updateById(updateJobEnInfo);
                } else if (param instanceof EnInfo) {
                    EnInfo enInfo = (EnInfo) ((Map) args[1]).get("param1");
                    EnInfo updateEnInfo = enInfoService.getById(enInfo.getId());
                    List<OpJob> list = jobService.lambdaQuery().eq(OpJob::getCompanyId, updateEnInfo.getId()).list();
                    if (CollUtil.isNotEmpty(list)) {
                        List<OpJob> remove = list.stream().filter(e -> e.getRecruitmentState() == 1 || e.getDelFlag()).collect(Collectors.toList());
                        if (!updateEnInfo.getEnabled() || updateEnInfo.getDelFlag() || updateEnInfo.getState() != 0) {
                            elasticsearchService.delete(JobPositionDocument.class, list.stream().map(OpJob::getId).toArray(String[]::new));
                        } else {
                            if (CollUtil.isNotEmpty(remove)) {
                                elasticsearchService.delete(JobPositionDocument.class, remove.stream().map(OpJob::getId).toArray(String[]::new));
                            }
                            list.removeAll(remove);
                            elasticsearchService.add(list.stream().map(e -> elasticsearchConvert.toJobPosition(e, updateEnInfo)).toArray(JobPositionDocument[]::new));
                        }
                    }
                }
                //专场修改时触发
                else if (param instanceof SsSession) {
                    try {
                        SsSession ssSession = (SsSession) ((Map) args[1]).get("param1");
                        SsSession ssSessionInfo = sessionService.getById(ssSession.getId());
                        if (!ssSessionInfo.getPubFlag()) {
                            List<OpJob> list = jobService.lambdaQuery().in(OpJob::getBsId, ssSessionInfo.getId()).eq(OpJob::getBsType, 1).eq(OpJob::getDelFlag, false).list();
                            log.info("取消发布专场，删除索引：" + ssSessionInfo);
                            if (CollUtil.isNotEmpty(list)) {
                                elasticsearchService.delete(JobPositionDocument.class, list.stream().map(OpJob::getId).toArray(String[]::new));
                            }

                        } else {
                            List<OpJob> list = jobService.lambdaQuery().in(OpJob::getBsId, ssSessionInfo.getId()).eq(OpJob::getBsType, 1).eq(OpJob::getDelFlag, false).list();

                            log.info("发布专场，创建索引：" + ssSessionInfo);
                            if (CollUtil.isNotEmpty(list)) {
                                elasticsearchService.add(list.stream().map(e -> {
                                    EnInfo updateEnInfo = enInfoService.getById(e.getCompanyId());
                                    return elasticsearchConvert.toJobPosition(e, updateEnInfo);
                                }).toArray(JobPositionDocument[]::new));

                            }


                        }
                    } catch (Exception e) {
                        log.error(e.getMessage(), e);
                    }
                }

                break;
            case INSERT:
                if (args[1] instanceof OpJob) {
                    OpJob insertJob = (OpJob) args[1];
                    //专场未发布不添加到es
                    if (insertJob.getBsType() == 1) {
                        SsSession session = sessionService.getById(insertJob.getBsId());
                        if (!session.getPubFlag()) {
                            break;
                        }
                    }
                    EnInfo insertJobEnInfo = enInfoService.getById(insertJob.getCompanyId());
                    if (insertJob.getRecruitmentState() == 0 && !insertJob.getDelFlag() && !insertJobEnInfo.getDelFlag() && insertJobEnInfo.getEnabled()) {
                        Integer postNum = insertJobEnInfo.getPostNum() + 1;
                        insertJobEnInfo.setPostNum(postNum);
                        enInfoService.getBaseMapper().updateById(insertJobEnInfo);
                        JobPositionDocument document = elasticsearchConvert.toJobPosition(insertJob, insertJobEnInfo);
                        elasticsearchService.add(document);
                    } else {
                        elasticsearchService.delete(JobPositionDocument.class, insertJob.getId());
                    }
                } else if (args[1] instanceof OpDeliveryHistoryMapper) {
                    OpDeliveryHistory history = (OpDeliveryHistory) args[1];
                    EnInfo insertDeliveryEnInfo = enInfoService.getById(history.getCompanyId());
                    int deliverNum = insertDeliveryEnInfo.getDeliverNum() + 1;
                    insertDeliveryEnInfo.setDeliverNum(deliverNum);
                    enInfoService.getBaseMapper().updateById(insertDeliveryEnInfo);
                }
                break;
            default:
                break;
        }
        return object;
    }

    @Override
    public Object plugin(Object target) {
        return Plugin.wrap(target, this);
    }

    @Override
    public void setProperties(Properties properties) {
    }
}
